package com.dataseek.iot.toolkit.tenant.aop;

import com.dataseek.iot.toolikit.common.enums.RspStatusEnum;
import com.dataseek.iot.toolikit.common.exception.UnAuthorizedException;
import com.dataseek.iot.toolikit.common.response.ResponseResult;
import com.dataseek.iot.toolkit.auth.util.JwtUtil;
import com.dataseek.iot.toolkit.tenant.config.DynamicDataSourceContextHolder;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 动态数据源切面拦截
 *
 * @author 李嘉
 * @version 1.0
 * @Description 动态数据源切面拦截
 * @date 2020/5/19 00:29
 */
@Slf4j
@Aspect
@Component
@Order(1) // 请注意：这里order一定要小于tx:annotation-driven的order，即先执行DynamicDataSourceAspectAdvice切面，再执行事务切面，才能获取到最终的数据源
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class DynamicDataSourceAspect {

    @Around("execution(* com.dataseek.iot..controller.*.*(..))")
    public Object doAround(ProceedingJoinPoint jp) throws Throwable {
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Object result = null;
        try {
            HttpServletRequest request = sra.getRequest();
            String token = request.getHeader("token");
            String requestUrl = request.getRequestURI();
            int beginIndex = requestUrl.indexOf("~") + 1;
            if (StringUtils.hasText(token) && beginIndex == 0) {
                //解析token
                String tenantAndUser;
                Claims claims = JwtUtil.parseJWT(token);
                tenantAndUser = claims.getSubject();
                log.info("tenantAndUser" + tenantAndUser);
                String tenantCode = tenantAndUser.split("~")[0];
                DynamicDataSourceContextHolder.setDataSourceKey(tenantCode);
                result = jp.proceed();
            } else if (!StringUtils.hasText(token) && beginIndex > 0) {
                int endIndex = requestUrl.indexOf("~", beginIndex);
                String tenantCode = requestUrl.substring(beginIndex, endIndex);
                if (!StringUtils.isEmpty(tenantCode)) {
                    DynamicDataSourceContextHolder.setDataSourceKey(tenantCode);
                    result = jp.proceed();
                }
            } else {
                DynamicDataSourceContextHolder.setDataSourceKey("master");
                result = jp.proceed();
            }
        }
        catch (UnAuthorizedException ex){
            ex.printStackTrace();
            log.error(ex.getMessage());
            throw new UnAuthorizedException(RspStatusEnum.UNAUTHORIZED);
        }
        catch (Exception ex) {
            ex.printStackTrace();
            log.error(ex.getMessage());
            throw new RuntimeException(ex.getMessage());
            //return new ResponseResult(RspStatusEnum.FAIL.getCode(), ex.getMessage());
        } finally {
            DynamicDataSourceContextHolder.clearDataSourceKey();
        }
        return result;
    }

}
